package com.cowmooed.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Enumeration;

/**
 * 日志拦截器
 * 用于记录请求和响应的详细信息
 */
@Component
@Slf4j
public class LogInterceptor implements HandlerInterceptor {

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     * 记录请求的基本信息
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 记录请求开始时间
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        
        // 获取当前时间
        String currentTime = LocalDateTime.now().format(FORMATTER);
        
        // 记录请求信息
        log.info("【请求开始】时间: {} | URL: {} | 方法: {} | IP: {}", 
                currentTime, 
                request.getRequestURI(), 
                request.getMethod(), 
                getClientIp(request));
        
        // 记录请求头信息
        logHeaders(request);
        
        // 记录请求参数
        logParameters(request);
        
        return true;
    }

    /**
     * 请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 可以在这里添加请求处理后的逻辑
    }

    /**
     * 在整个请求结束之后被调用，也就是在DispatcherServlet渲染了对应的视图之后执行
     * 记录请求处理时间和响应状态码
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 计算请求处理时间
        long startTime = (long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        
        // 获取当前时间
        String currentTime = LocalDateTime.now().format(FORMATTER);
        
        // 记录异常信息（如果有）
        if (ex != null) {
            log.error("【请求异常】时间: {} | URL: {} | 异常: {}", 
                    currentTime, 
                    request.getRequestURI(), 
                    ex.getMessage(), ex);
        }
        
        // 记录请求完成信息
        log.info("【请求结束】时间: {} | URL: {} | 状态码: {} | 处理时间: {}ms", 
                currentTime, 
                request.getRequestURI(), 
                response.getStatus(), 
                executionTime);
    }

    /**
     * 获取客户端真实IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 如果是多级代理，取第一个IP地址
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }

    /**
     * 记录请求头信息
     */
    private void logHeaders(HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            StringBuilder headers = new StringBuilder("【请求头】");
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                String headerValue = request.getHeader(headerName);
                // 避免记录敏感信息
                if ("authorization".equalsIgnoreCase(headerName)) {
                    headers.append(headerName).append(": [已加密] | ");
                } else {
                    headers.append(headerName).append(": '").append(headerValue).append("' | ");
                }
            }
            if (headers.length() > 6) { // 如果有请求头信息
                headers.setLength(headers.length() - 3); // 移除最后一个分隔符
                log.debug(headers.toString());
            }
        }
    }

    /**
     * 记录请求参数
     */
    private void logParameters(HttpServletRequest request) {
        Enumeration<String> paramNames = request.getParameterNames();
        if (paramNames != null && paramNames.hasMoreElements()) {
            StringBuilder params = new StringBuilder("【请求参数】");
            while (paramNames.hasMoreElements()) {
                String paramName = paramNames.nextElement();
                String paramValue = request.getParameter(paramName);
                params.append(paramName).append(": '").append(paramValue).append("' | ");
            }
            params.setLength(params.length() - 3); // 移除最后一个分隔符
            log.debug(params.toString());
        }
    }
}